在C++中,我們利用”//”雙斜線來表示單行的註解。當我們在讀取檔案時,若是遇到註解,可以跳過註解的部分嗎?
這時,我們可以使用”state”(狀態)這個語法,來定義檔案中不同區塊的讀取規則。
首先,在Lex檔案中,我們需要先自行定義state的名稱。
在下面的例子中,我們將註解的state命名為”COMMENT”,定義於”Definition”區塊中。
%x COMMENT
接著,我們使用BEGIN
表示進入某個state。
以剛剛的例子來說,單行註解的符號為雙斜線,故在讀到雙斜線時,便會進入”COMMENT”的state。
\/\/ { BEGIN COMMENT; }
在正則表達式中,我們使用<>
來表示該規則只適用於特定的state。
例如,我們若不想讀取COMMENT state的內容時,便可直接跳過該區段。(要注意換行符號!)
<COMMENT>[^\n]* { ; }
最後,當該state結束時,同樣可以利用BEGIN
切換至其他state。初始state預定義為0 (Initial)。
在單行註解中,以換行符號作為結束。因此,在讀取到換行符號時,要回到初始state。
<COMMENT>\n { BEGIN 0; }
如此一來,即使是不同的規則也可以在同一個編譯器下操作了!
給定一個C++程式碼,請將程式碼輸出到terminal中,但略過註解處。
註解的state在這裡定義。
%{
%}
%x COMMENT
這裡分別定義一般state與註解state的規則。
%%
\/\/ { BEGIN COMMENT; }
<COMMENT>[^\n]* { ; }
<COMMENT>\n { BEGIN 0; ECHO; }
.|\n { ECHO; }
在這裡,我們碰到了一個新玩意ECHO
。熟悉script語法的讀者應該對此不陌生,就是把指定字串輸出到terminal中。在這裡的用法也一樣,非常方便。
這部分跟前一個範例一樣。
%%
int yywrap(void) {
return 1;
}
int main(void) {
const char* sFile = "file.cpp";
FILE* fp = fopen(sFile, "r");
if (fp == NULL) {
printf("cannot open %s\n", sFile);
return -1;
}
yyin = fp;
yylex();
return 0;
}
%{
%}
%x COMMENT
%%
\/\/ { BEGIN COMMENT; }
<COMMENT>[^\n]* { ; }
<COMMENT>\n { BEGIN 0; ECHO; }
.|\n { ECHO; }
%%
int yywrap(void) {
return 1;
}
int main(void) {
const char* sFile = "file.cpp";
FILE* fp = fopen(sFile, "r");
if (fp == NULL) {
printf("cannot open %s\n", sFile);
return -1;
}
yyin = fp;
yylex();
return 0;
}
#include <cstdio>
int main() {
int age = 100; // Input user's age
char* name = "BarleyTea"; // Input user's name
printf("Hi, my name is %s. I am %d years old.\n", name, age); // print user info
}
#include <cstdio>
int main() {
int age = 100;
char* name = "BarleyTea";
printf("Hi, my name is %s. I am %d years old.\n", name, age);
}
State是一項很實用的工具,尤其是一份檔案裡遇到不同區塊的規則不同的狀況時,便可以用State來定義每個區塊的規則。
ECHO則是lex當中最簡單的內建函式,可以直接印出讀取到的字串。